package com.act.moudles.baseAct.service.impl;

import com.act.components.UserComponent;
import com.act.config.VarsTypeEnums;
import com.act.constant.LoginTypeEnums;
import com.act.constant.TaskAnoConstants;
import com.act.constant.UserTypeEnums;
import com.act.moudles.act.service.ActDeployService;
import com.act.moudles.baseAct.dao.OnlineDeployRecordsDao;
import com.act.moudles.baseAct.dao.TaskAnoDao;
import com.act.moudles.baseAct.dao.TaskAnoVarsDao;
import com.act.moudles.baseAct.entity.OnlineDeployRecords;
import com.act.moudles.baseAct.entity.TaskAno;
import com.act.moudles.baseAct.entity.TaskAnoVars;
import com.act.moudles.user.entity.User;
import com.act.utils.PinYinUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.act.moudles.baseAct.dao.OnlineDeployDao;
import com.act.moudles.baseAct.entity.OnlineDeploy;
import com.act.moudles.baseAct.service.OnlineDeployService;
import org.activiti.engine.repository.Deployment;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (OnlineDeploy)表服务实现类
 *
 * @author makejava
 * @since 2023-05-09 21:45:26
 */
@Service("onlineDeployService")
public class OnlineDeployServiceImpl extends ServiceImpl<OnlineDeployDao, OnlineDeploy> implements OnlineDeployService {


    @Resource
    private UserComponent userComponent;

    @Resource
    private OnlineDeployDao onlineDeployDao;

    @Resource
    private ActDeployService actDeployService;

    @Resource
    private OnlineDeployRecordsDao onlineDeployRecordsDao;

    @Resource
    private TaskAnoDao taskAnoDao;

    @Resource
    private TaskAnoVarsDao taskAnoVarsDao;



    @Override
    public int countByBpmnFileNameFromUser(String bpmn) {
        User user = userComponent.getCurrentUser(LoginTypeEnums.WEB.getType());
        return onlineDeployDao.selectOneByBpmnFileName(bpmn,user.getUserId(),userComponent.getUserTenAntId()) == null?0:1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void uploadFileAndDeploy(MultipartFile bpmnFile, MultipartFile pngFile,String bpmnFileName,String  deployName) throws IOException {
        User user = userComponent.getCurrentUser(LoginTypeEnums.WEB.getType());

        String basicPath = userComponent.getUserBasicPath();
        String locBpmnFilePath = basicPath + bpmnFile.getOriginalFilename();
        String locPngFilePath = basicPath + pngFile.getOriginalFilename();

        //保存到本地
        FileUtils.copyToFile(bpmnFile.getInputStream(),new File(locBpmnFilePath));
        FileUtils.copyToFile(pngFile.getInputStream(),new File(locPngFilePath));

        Boolean isAdd = false;
        OnlineDeploy  onlineDeploy = onlineDeployDao.selectOneByBpmnFileName(bpmnFileName,user.getUserId(),userComponent.getUserTenAntId());
        if(onlineDeploy == null){
            onlineDeploy = new OnlineDeploy();
            onlineDeploy.setUpdCounts(0);
            isAdd = true;
        }
        try {
            Map<String,String> map = actDeployService.digDeploy(locBpmnFilePath,locPngFilePath,bpmnFile.getOriginalFilename().split(".bpmn")[0],userComponent.getUserTenAntId());
            //新增或者修改在线部署
            onlineDeploy.setUpdCounts(onlineDeploy.getUpdCounts() + 1);
            onlineDeploy.setDelFlag(1);
            onlineDeploy.setUserName(user.getRealName());
            onlineDeploy.setUserOrgId(user.getOrgId());
            if(isAdd){
                onlineDeploy.setCreateBy(user.getUserId());
                onlineDeploy.setCreateTime(new Date());
            }else {
                onlineDeploy.setUpdateBy(user.getUserId());
                onlineDeploy.setUpdateTime(new Date());
            }
            onlineDeploy.setProcdefId(map.get("id"));
            onlineDeploy.setProcdefKey(map.get("procKey"));
            onlineDeploy.setProcdefDes(map.get("des"));
            onlineDeploy.setUserId(user.getUserId());
            onlineDeploy.setUserProcdefKey(userComponent.getUserTenAntId()+"_"+onlineDeploy.getProcdefKey());
            onlineDeploy.setTenantId(userComponent.getUserTenAntId());
            if(user.getUserType() - UserTypeEnums.PERSON.getUserType() == 0){
                onlineDeploy.setRemark("公司项目");
            }else {
                onlineDeploy.setRemark("个人项目");
            }
            onlineDeploy.setDepeloyName(deployName);
            onlineDeploy.setAnlRes("解析完成");
            onlineDeploy.setBpmnPath(locBpmnFilePath);
            onlineDeploy.setPngPath(locPngFilePath);
            onlineDeploy.setBpmnFileName(bpmnFileName);
        }catch (Exception e){
            e.printStackTrace();
            onlineDeploy.setAnlRes("解析异常："+e.getMessage());
            new File(locBpmnFilePath).delete();
            new File(locPngFilePath).delete();
        }
        if(isAdd){
            save(onlineDeploy);
        }else {
            updateById(onlineDeploy);
        }
        //构建任务方法
        addOrUpdTaskAo(onlineDeploy.getProcdefKey(),onlineDeploy.getTenantId(),onlineDeploy.getUserProcdefKey() );

        createRecord(onlineDeploy);
    }

    @Override
    public IPage<OnlineDeploy> pageDeploy(Page<OnlineDeploy> page, OnlineDeploy onlineDeploy) {
        User user = userComponent.getCurrentUser(LoginTypeEnums.WEB.getType());
        if(user.getUserType() - UserTypeEnums.SYSTEM.getUserType() != 0){
            String tenantId = userComponent.getUserTenAntId();
            onlineDeploy.setTenantId(tenantId);
        }
        return page(page,onlineDeploy.query());
    }

    /**
     * 解析流程方法
     * @param flowKey
     * @param tenantId
     */
    public void addOrUpdTaskAo(String flowKey,String tenantId,String userFlowKey){
        List<TaskAno> taskAnoList = actDeployService.anlTaskAnoByFlow(flowKey,tenantId);
        if(CollectionUtils.isEmpty(taskAnoList)){
            return;
        }

        //1.更具流程key和住户ID查询
        List<TaskAno>  dbList = taskAnoDao.selectList(TaskAno.builder().procdefKey(flowKey).tenantId(tenantId).build().query());
        Map<String,TaskAno> sidMap = new HashMap<>();
        for(TaskAno o : dbList){
            sidMap.put(o.getSid(),o);
        }

        for(TaskAno o : taskAnoList){
            o.setUserFlowKey(userFlowKey);
            TaskAno db = sidMap.get(o.getSid());
            if(db == null){
                //新增
                taskAnoDao.insert(completeTaskAno(o));
            }
            if(db != null ){
                //修改
                dbList.remove(db);
                if(db.getTaskName().equals(o.getTaskName()) || db.getTaskSort() - o.getTaskSort() != 0){
                    db.setCreateTime(new Date());
                    db.setTaskName(o.getTaskName());
                    db.setTaskSort(o.getTaskSort());
                    taskAnoDao.updateById(db);
                }
            }
            dealTaskVars(o);
        }

        if(!CollectionUtils.isEmpty(dbList)){
            taskAnoDao.deleteByIds(dbList.stream().map(TaskAno::getId).collect(Collectors.toList()));
            taskAnoVarsDao.deleteBatchByAnoIds(dbList.stream().map(TaskAno::getId).collect(Collectors.toList()));
        }
    }


    /**
     * 新增流程变量
     * @param taskAno
     */
    private void  dealTaskVars(TaskAno taskAno){
        String ass = taskAno.getAssigine();
        if(StringUtils.isEmpty(ass)){
            return;
        }
        TaskAnoVars taskAnoVars = taskAnoVarsDao.selectByAnoIdAndVarKey(taskAno.getId(),ass);
        if(taskAnoVars == null){
            taskAnoVars = TaskAnoVars.builder()
                    .anoId(taskAno.getId())
                    .canEdit(0)
                    .varKey(dealAss(ass))
                    .createTime(new Date())
                    .varName(TaskAnoConstants.task_ano_var_default)
                    .varType(VarsTypeEnums.PRE_VARS.getVarType())
                    .build();
            taskAnoVarsDao.insert(taskAnoVars);
            return;
        }
    }


    /**
     * 完善
     * @param taskAnoFromAct
     */
    private  TaskAno completeTaskAno(TaskAno  taskAnoFromAct){
        StringBuffer pySb = new StringBuffer();
        for(int i = 0 ; i < taskAnoFromAct.getTaskName().length();i++){
           String py = PinYinUtil.getPinyin(taskAnoFromAct.getTaskName().charAt(i)+"");
            pySb.append(py.charAt(0));
        }
        taskAnoFromAct.setTaskCode(pySb.toString());
        taskAnoFromAct.setCreateTime(new Date());
        return  taskAnoFromAct;
    }



    /**
     * 生成历史记录
     * @param o
     */
    private void createRecord(OnlineDeploy  o){
        OnlineDeployRecords r = new OnlineDeployRecords();
        r.setDeId(o.getDeId());
        r.setCreateBy(o.getCreateBy());
        r.setCreateTime(o.getCreateTime());
        r.setRemark(o.getRemark());
        r.setProcdefId(o.getProcdefId());
        r.setProcdefKey(o.getProcdefKey());
        r.setProcdefDes(o.getProcdefDes());
        r.setTenantId(o.getTenantId());
        r.setUserId(o.getUserId());
        r.setUserProcdefKey(o.getUserProcdefKey());
        r.setUserOrgId(o.getUserOrgId());
        r.setDepeloyName(o.getDepeloyName());
        r.setAnlRes(o.getAnlRes());
        r.setBpmnFileName(o.getBpmnFileName());
        r.setBpmnPath(o.getBpmnPath());
        r.setPngPath(o.getPngPath());
        r.setUserName(o.getUserName());
        onlineDeployRecordsDao.insert(r);
    }

    private String  dealAss(String ass){
        if(StringUtils.isEmpty(ass)){
            return null;
        }
        if(ass.startsWith("$") || ass.startsWith("#")){
            ass = ass.substring(2,ass.length()-1);
        }

        return ass;
    }
}

